import React, {
  useCallback,
  useEffect,
  useImperativeHandle,
  useRef,
  useState,
} from 'react';

import { Ace } from 'ace-builds';
import {
  IEditorAceProps,
  IEditorOperateEvent,
  IEditorRefHandles,
} from './CodeEditorConfig';

import ReactAce from 'react-ace';

//引入ace 后续修改自定义标签用到
import * as ace from 'ace-builds/src-noconflict/ace';

import 'ace-builds/src-noconflict/snippets/java';
import 'ace-builds/src-noconflict/snippets/javascript';
import 'ace-builds/src-noconflict/snippets/json';
import 'ace-builds/src-noconflict/snippets/sql';

// 模式
import 'ace-builds/src-noconflict/mode-java';
import 'ace-builds/src-noconflict/mode-javascript';
import 'ace-builds/src-noconflict/mode-json';
import 'ace-builds/src-noconflict/mode-sql';

// 主题颜色
import 'ace-builds/src-noconflict/theme-mono_industrial';
import 'ace-builds/src-noconflict/theme-monokai';
import 'ace-builds/src-noconflict/theme-solarized_dark';
import 'ace-builds/src-noconflict/theme-xcode';

import 'ace-builds/src-noconflict/ext-language_tools'; // 代码提示

import { formatCodeByLanguage } from '@/utils/FormatterUtil';
import { Spin } from 'antd';
import 'brace';
import 'brace/ext/searchbox';
import { EditorContainerLayout } from './CodeEditorStyle';
import { resetEditorPosition } from './CodeEditorUtil';

ace.config.set('basePath', '/assets/ui/');
ace.config.set('modePath', '');
ace.config.set('themePath', '');

type IEditorEntity = Ace.Editor;

interface Props extends IEditorAceProps {}

export const CodeEditorAce: React.FC<Props> = (props) => {
  const {
    handleRef,
    value,
    language = 'sql',
    theme,
    fontSize = 14,
    readOnly = false,
    format,
    onChange,
    saveChange,
    completers,
    onLoad,
    ...rest
  } = props;

  const [code, setCode] = useState(value);
  const [loading, setLoading] = useState<boolean>(false);

  // 编辑器实例化对象
  const editorRef = useRef<IEditorEntity>(); // 编辑器实例

  /** 获取内容 */
  const getValue = () => {
    let value: string = '';
    if (editorRef?.current) {
      const editor = editorRef.current;
      value = editor.getValue();
    }

    return value;
  };

  /** 设置内容 */
  const setValue = (value: any = '') => {
    if (editorRef?.current) {
      const editor = editorRef.current;
      editor.session.setValue(value);
    }
  };

  /** 撤销 */
  const handleUndoChange = () => {
    if (editorRef?.current) {
      const editor: IEditorEntity = editorRef.current;
      editor.undo();
      editor.focus();
    }
  };

  /** 重做 */
  const handleRedoChange = () => {
    if (editorRef?.current) {
      const editor: IEditorEntity = editorRef.current;
      editor.redo();
      editor.focus();
    }
  };

  /** 格式化 */
  const handleFormatChange = useCallback(
    (value?: any) => {
      if (editorRef?.current) {
        const txt = value || getValue();

        setLoading(true);

        formatCodeByLanguage(txt, language).then((res) => {
          setValue(res);
          setLoading(false);
        });
      }
    },
    [language],
  );

  /** 光标处插入文本 */
  const onEditorInsert = (data: string) => {
    if (editorRef.current && data) {
      const editor: IEditorEntity = editorRef.current;

      if (!editor.getReadOnly()) {
        editor.getSession().insert(editor.getCursorPosition(), data);
        editor.focus();
        // 插入内容中以括号结尾，则光标定位至括号内
        const { row, column } = editor.getCursorPosition();
        editor.moveCursorToPosition({
          row,
          column: resetEditorPosition(data, column),
        });
      }
    }
  };

  /**
   * 获取选中代码内容
   * @returns
   */
  const getEditorSelectionValue = () => {
    let selectedCode = '';
    if (editorRef.current) {
      const editor: IEditorEntity = editorRef.current;

      selectedCode =
        editor.session.getTextRange(editor.getSelectionRange()) ?? '';
    }

    return selectedCode;
  };

  const onEditorRun = () => {
    const val = getEditorSelectionValue() || getValue();
    console.log(val);
  };

  /**
   * 点击相关事件：插入、撤销、重做等
   * @param event
   */
  const onEditorEvent = (event: IEditorOperateEvent) => {
    const { type, data = '' } = event;

    switch (type) {
      case 'init':
        setValue('');
        onEditorInsert(data);
        break;
      case 'undo':
        handleUndoChange();
        break;
      case 'redo':
        handleRedoChange();
        break;
      case 'insert':
        onEditorInsert(data);
        break;
      case 'run':
        onEditorRun();
        break;
      default:
        break;
    }
  };

  /** editor加载完成后，返回编辑器实例化对象，并赋值到ref */
  const handleOnloadChange = useCallback(
    (editor: IEditorEntity) => {
      editorRef.current = editor;

      if (onLoad) {
        onLoad(editor);
      }
    },
    [onLoad],
  );

  /** 监听输入 */
  const handleCodeChange = useCallback(
    (value: string, event?: any) => {
      setCode(value);

      if (onChange) {
        onChange(value, event);
      }
    },
    [onChange],
  );

  /** 将列表更新方法暴露给父组件 */
  useImperativeHandle(handleRef, (): IEditorRefHandles => {
    return {
      getValue: () => getValue(),
      setValue: (value: string) => setValue(value),
      undo: () => handleUndoChange(),
      redo: () => handleRedoChange(),
      insert: (value: string) => onEditorInsert(value),
      run: () => onEditorRun(),
      editorEvent: (event: IEditorOperateEvent) => onEditorEvent(event),
      format: (value?: string) => handleFormatChange(value),
    };
  });

  /** 自定义快捷键 */
  const createCommands = () => {
    return [
      {
        name: 'run',
        bindKey: { win: 'Ctrl-b', mac: 'Command-b' },
        exec: () => onEditorRun(),
      },
      {
        //键盘指令
        name: 'save',
        bindKey: { win: 'Ctrl-s', mac: 'Command-s' },
        exec: () => {
          if (saveChange) {
            saveChange();
          }
        },
      },
    ];
  };

  /** 自定义代码提示 */
  useEffect(() => {
    if (editorRef?.current && completers?.length) {
      const editor = editorRef.current;
      editor.completers?.push({
        getCompletions: function (editor, session, pos, prefix, callback) {
          if (prefix?.length === 0) {
            return callback(null, []);
          }
          if (completers?.length) {
            callback(null, completers);
          }
        },
      });
    }
  }, [completers]);

  useEffect(() => {
    if (format) {
      handleFormatChange();
    }
  }, [handleFormatChange, format]);

  return (
    <EditorContainerLayout>
      <Spin spinning={loading}>
        <ReactAce
          ref={handleRef}
          name={Math.random().toString(36).slice(2)}
          highlightActiveLine // 突出活动线
          fontSize={fontSize}
          showPrintMargin={false} // 分割线
          mode={language}
          theme={theme}
          value={code}
          readOnly={readOnly} // 只读
          showGutter={true} // 行号区显示
          onChange={handleCodeChange}
          onLoad={handleOnloadChange}
          setOptions={{
            enableBasicAutocompletion: true, // 启用基本自动完成功能
            enableLiveAutocompletion: true, //启用实时自动完成功能 （比如：智能代码提示）
            enableSnippets: true, // 启用代码段
            showLineNumbers: true,
            tabSize: 2,
            wrap: true, // 启用换行
            fixedWidthGutter: true, // 固定行号区域宽度
            useWorker: false,
            placeholder: '请输入内容',
          }}
          editorProps={{ $blockScrolling: true }}
          commands={createCommands()}
          style={{
            width: '100%',
            height: '100%',
          }}
          {...rest}
        />
      </Spin>
    </EditorContainerLayout>
  );
};
